/* 
 * Copyright [2018] [Alex/libo(liboware@gmail.com)]
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.bind.facade;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

import com.google.inject.Binding;
import com.google.inject.Key;
import com.hyts.bind.base.BaseInjector;
import com.hyts.bind.domain.BindDomains;
import com.hyts.bind.injector.DefaultClassInjector;

/** 
 * @author LiBo/Alex
 * @see com.hyts.bind.base.BaseInjector
 * @see com.hyts.bind.injector.DefaultClassInjector
 * @since V1.0 
 * @version V1.0 
 */
public final class BindContext {
     
    
    /**  
     * @fieldName injector
     * @fieldType BaseInjector
     */ 
    private  volatile BaseInjector injector;
    
    /**  
     * @fieldName bindDomains
     * @fieldType BindDomains
     */ 
    private  volatile BindDomains bindDomains;
    
    /**  
     * <p>是否初始化</p> 
     * @fieldName init
     * @fieldType Boolean
     */ 
    private  AtomicBoolean init = new AtomicBoolean(false);
    
    
    /**  
     * <b>init</b>
     * <p>初始化绑定关系对象</p>
     * @return
     * @exception
     */ 
    public void init() {
        injector = DefaultClassInjector.getInstance().initBinding(bindDomains);
        //        if(!init.get()) {
//            while(init.compareAndSet(false, true)) {}
//        }
    }
    
    
    /**  
     * <b>getBean</b>
     * <p>获取绑定对象</p>
     * @param clazz
     * @return
     * @exception
     */ 
    public  <T> T getBean(Class<T> clazz){
        init();
        return injector.getInjector().getInstance(clazz);
    }
    
    
    /**  
     * <b>getBindings</b>
     * <p>获取绑定关系集合</p>
     * @return
     * @exception
     */ 
    public  Map<Key<?>, Binding<?>> getBindings() {
        init();
        return injector.getInjector().getBindings();
    }
    
    
    /**  
     * <b>getBinding</b>
     * <p>根据绑定key获取绑定关系对象</p>
     * @param key
     * @return
     * @exception
     */ 
    public  <T> Binding<T> getBinding(Key<T> key) {
        init();
        return injector.getInjector().getBinding(key);
    }
    
    /**  
     * <b>createBindDomains</b>
     * <p>创建绑定关系域对象集合</p>
     * @return
     * @exception
     */ 
    public BindDomains createBindDomains() {
        bindDomains = new BindDomains();
        return bindDomains;
    }

    /**
     * 获取BindDomains
     * @return
     */
    public BindDomains getBindDomains() {
         bindDomains = Optional.ofNullable(bindDomains).orElse(new BindDomains());
         return bindDomains;
    }
}
